from codecs import StreamReader
import math
import os
import struct
import bpy
import mathutils
from mathutils import Euler

from .Import_Animation import read_animation
from .Import_Kart import read_kart
from .Import_Charater import read_character

#animation AA 47 2A 05 4B 22

def read_float32(f):
    return round(struct.unpack('f', f.read(4))[0], 4)


def read_float16(f):
    return round(struct.unpack('f', f.read(2))[0], 4)


def read_int32(f):
    return int.from_bytes(f.read(4), 'little')


def read_int16(f):
    return int.from_bytes(f.read(2), 'little')

class PartObj():
    def __init__(self):
        super().__init__()
        self.name = ''
        self.vertices = []
        self.uvs = []
        self.indices = []
        self.uvindices = []
        self.normals = []
        self.child = []
        self.coord = []
        self.scale_base = []
        self.scale_what = []
        self.rotation = []

        self.bbmax = []
        self.bbmin = []

lattice_axis = [[[1, 3, 5, 7],[0, 2, 4, 6]], [[2, 3, 6, 7],[0, 1, 4, 5]], [[4, 5, 6, 7],[0, 1, 2, 3]]]


def write_obj(Obj:PartObj, use_smooth):
    mesh = bpy.data.meshes.new("mesh")  # add a new mesh
    indices = []
    for indice in Obj.indices:
        for i in range(0, len(indice), 3):
            indices.append((indice[i]-1, indice[i+1]-1, indice[i+2]-1))
    mesh.from_pydata(Obj.vertices, [], indices)
    for f in mesh.polygons:
        f.use_smooth = True
    mesh.update()
    obj = bpy.data.objects.new(Obj.name, mesh)
    obj.data = mesh

    obj.data.use_auto_smooth = use_smooth
    obj.data.auto_smooth_angle = math.radians(80)

    bpy.context.collection.objects.link(obj)
    bpy.context.view_layer.objects.active = obj
    obj.location = Obj.coord
    # obj.scale = Obj.scale
    # obj.rotation_euler = (math.radians(Obj.rotation[0])*90, math.radians(Obj.rotation[1])*90, 0)

    lattice = None
    if len(Obj.vertices) > 0:
        lattice = bpy.data.lattices.new("Lattice")
        lattice_obj = bpy.data.objects.new("Lattice", lattice)
        bpy.context.collection.objects.link(lattice_obj)
        mod = obj.modifiers.new("Lattice", 'LATTICE')
        mod.object = lattice_obj
        lattice_obj.parent = obj
        if len(Obj.bbmax) != 0:
            if lattice_obj.dimensions.x == 0 or lattice_obj.dimensions.y == 0 or lattice_obj.dimensions.z == 0:
                lattice_obj.select_set(True)
                bpy.ops.object.delete()
                obj.modifiers.clear()
    obj.select_set(True)

    mesh = bpy.context.selected_objects[0].data

    mesh.uv_layers.new(name="UVMap")

    for face in obj.data.polygons:
        asdf = 0
        for loop_idx in face.loop_indices:
            obj.data.uv_layers.active.data[loop_idx].uv = Obj.uvs[Obj.uvindices[face.index][asdf]]
            asdf += 1
            if asdf == 3:
                asdf = 0

    if lattice != None:
        dim = lattice_obj.dimensions
        for idxA in range(3):
            for idxB in range(3):
                if Obj.scale_base[idxA][idxB] == 1.0 or Obj.scale_base[idxA][idxB] == -1.0 or Obj.scale_base[idxA][idxB] == 0.0:
                    sc = 0
                else:
                    obj.scale[2] = -1.0
                    sc = ((Obj.scale_base[idxA][idxB]*dim[idxB])/2)*-1
                for point in range(4):
                    pointidx = lattice_axis[idxB][0][point]
                    lattice.points[pointidx].co_deform[idxA] += sc
                for point in range(4):
                    pointidx = lattice_axis[idxB][1][point]
                    lattice.points[pointidx].co_deform[idxA] -= sc
        bpy.ops.object.transform_apply(location = False, scale = True, rotation = False)
        
    obj.data.use_auto_smooth = True


    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.object.mode_set(mode='OBJECT')

    obj.select_set(False)

    if len(Obj.child) != 0:
        for child in Obj.child:
            childobj = write_obj(child, True)
            childobj.parent = bpy.data.objects[Obj.name]

    return obj

def read_1s(filepath):
    f = open(filepath, 'rb')
    MagicNumber = f.read(6)
    if MagicNumber == b'\xAA\x47\x49\x02\x8C\x07':
        read_kart(filepath)
    elif MagicNumber == b'\xAA\x47\x44\x04\x6F\x18':
        read_character(filepath)
    elif MagicNumber == b'\xAA\x47\xCB\x04\x8A\x1E':
        read_animation(filepath)
